package cn.itcast.nems.base.web.controller.o;

import cn.hutool.core.lang.Assert;
import cn.itcast.ic.common.bean.BizError;
import cn.itcast.ic.common.exception.BizException;
import cn.itcast.nems.common.enumeration.CustomBizError;
import cn.itcast.nems.enrol.dto.EnrolCreateVO;
import cn.itcast.nems.enrol.service.EnrolService;
import cn.itcast.nems.manager.util.Md5Util;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.time.Duration;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;

@Slf4j
@RestController
@RequestMapping("/o/ems/proxy")
@RequiredArgsConstructor
public class EmsProxyController {
    @Value("${ems.domain}")
    private String emsDomain;
    @Value("${ems.signature}")
    private String emsSignature;
    @Value("${ems.cid}")
    private String cid;
    @Autowired
    private EnrolService enrolService ;

    private final OkHttpClient httpClient = new OkHttpClient.Builder()
            .connectTimeout(Duration.ofMinutes(3))
            .readTimeout(Duration.ofMinutes(3))
            .writeTimeout(Duration.ofMinutes(3))
            .build();
    @RequestMapping("**")
    public void doProxy(
            @RequestParam Map<String, String> paramsInput,
            HttpServletRequest request,
            HttpServletResponse response
    ) throws IOException {
        var params = new TreeMap<>(paramsInput);
        Assert.isTrue(StringUtils.hasText(params.ceilingKey("sid")), "sid不存在");
        EnrolCreateVO createVO = enrolService.getEnrolCreateVO(params.get("sid"));
        params.put("ts", String.valueOf(System.currentTimeMillis())) ;
        params.put("cid", cid) ;
        var originUrl = request.getRequestURL().toString();
        var pathAndQuery = originUrl.substring(originUrl.indexOf("/o/ems/proxy") + "/o/ems/proxy".length());
        var emsUrl = emsDomain + pathAndQuery;
        params.remove("sid") ;
        Md5Util.handlerSigUrlByMd5(params, emsSignature);
        log.info("ORIGIN URL : {}", originUrl);
        log.info("EMS  URL : {}", emsUrl);
        log.info("EMS PROXY PARAMS : {}", params);
        var method = request.getMethod();
        var reqBuilder = new Request.Builder()
                .url(emsUrl)
                .header("login_user", createVO.getOperationEmail());;
        if (method.equalsIgnoreCase("GET")) {
            reqBuilder = reqBuilder.get();
        } else if (method.equalsIgnoreCase("POST")) {
            var fb = new FormBody.Builder();
            params.forEach(fb::add);
            reqBuilder = reqBuilder.post(fb.build());
        } else {
            throw new BizException(CustomBizError.message(BizError.BAD_REQUEST,String.format("不支持的请求方法%s", method)));
        }
        try (var rsp = httpClient.newCall(reqBuilder.build()).execute()) {
            log.info("CODE : {}", rsp.code());
            response.setStatus(rsp.code());
            rsp.headers().names().forEach(name -> {
                log.info("HEADER : {} : {}", name, rsp.header(name));
                response.setHeader(name, rsp.header(name));
            });
            try (var is = Objects.requireNonNull(rsp.body()).byteStream()) {
                try (var os = response.getOutputStream()) {
                    StreamUtils.copy(is, os);
                }
            }
        }
    }
}
